//
//  ConsumeQueue.m
//  BaseProject
//
//  Created by HanFeng on 14-4-3.
//  Copyright (c) 2014年 mafengwo. All rights reserved.
//

#import "ConsumeQueue.h"
#import <objc/runtime.h>

static void * __consumer_priority_key__ = nil;
@implementation Consumer (Priority)

- (NSInteger)priority
{
    NSNumber *pn = objc_getAssociatedObject(self, &__consumer_priority_key__);
    if (pn == nil) {
        return ConsumerPriority_Default;
    }
    return [pn integerValue];
}

- (void)setPriority:(NSInteger)priority
{
    priority = MAX(priority, 0);
    
    objc_setAssociatedObject(self, &__consumer_priority_key__, @(priority), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

@interface ConsumeQueue () {
    NSMutableArray *_priorityQueue;
}

@end

@implementation ConsumeQueue

- (instancetype)init
{
    self = [super init];
    if (self) {
        _priorityQueue = [[NSMutableArray alloc] initWithCapacity:8];
    }
    return self;
}

- (NSArray *)priorityQueue
{
    return [_priorityQueue copy];
}

- (void)addConsumer:(Consumer *)consumer
{
    if (consumer.priority == ComsumerPriority_Undefined) {
        consumer.priority = ConsumerPriority_Default;
    }
    [self addConsumer:consumer priority:ConsumerPriority_Default];
}

- (void)addConsumer:(Consumer *)consumer priority:(NSInteger)priority
{
    if (consumer == nil) return;

    consumer.priority = priority;
    [self _addConsumerToPriorityQueue:consumer];
}

- (void)_addConsumerToPriorityQueue:(Consumer *)consumer
{
    NSInteger insertIdx = _priorityQueue.count;
    
    if (_priorityQueue.lastObject) {
        // 这是一个优化，找最后一个，因为通常都是default，priority变化不频繁，可以直接加到队尾
        Consumer *c = _priorityQueue.lastObject;
        if (c.priority >= consumer.priority) {
            [_priorityQueue addObject:consumer];
            return;
        }
    }
    
    for (int i = 0; i < _priorityQueue.count; i++) {
        Consumer *c = _priorityQueue[i];
        if (c.priority < consumer.priority) {
            // 第一个比自己低优先级的
            insertIdx = i;
            break;
        }
    }
    
    [_priorityQueue insertObject:consumer atIndex:insertIdx];
}

- (void)deleteConsumer:(Consumer *)consumer
{
    [_priorityQueue removeObject:consumer];
}

- (BOOL)consume:(ConsumedObject *)object
{
    return [self consume:object outConsumer:nil];
}

- (BOOL)consume:(ConsumedObject *)object outConsumer:(Consumer **)consumer
{
    if (object == nil) return NO;

    Consumer *theConsumer = nil;
    
    for (Consumer *c in _priorityQueue) {
        if (c.consumeBlock && c.consumeBlock(object)) {
            theConsumer = c;
            break;
        }
    }
    
    if (theConsumer) {
        if (consumer) *consumer = theConsumer;
        DLog(@"%@ 已经被 %@ 消费了", object, theConsumer);
        return YES;
    }
    
    DLog(@"%@ 没有被消费掉", object);
    return NO;
}

- (void)clearAllConsumers
{
    [_priorityQueue removeAllObjects];
}

@end
